//
//  NSString+MD5.m
//  lib51PKUserCenter
//
//  Created by L.T.ZERO on 14-4-24.
//  Copyright (c) 2014年 51pk. All rights reserved.
//

#import "NSString+Secret.h"
#import <Security/Security.h>
#import <math.h>
#import "GTMBase64.h"
#include <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCrypto.h>
#import <Accelerate/Accelerate.h>
#import <regex.h>

typedef struct rc4_key_str
{
    unsigned char state[256];
    unsigned char x;
    unsigned char y;
} rc4_key;

static void swap_byte(unsigned char *a, unsigned char *b);

void prepare_key(unsigned char *key_data_ptr,
        int key_data_len,
        rc4_key *key)
{
    unsigned char index1;
    unsigned char index2;
    unsigned char* state;
    short counter;

    state = &key->state[0];
    for(counter = 0; counter < 256; counter++)
        state[counter] = counter;
    key->x = 0;
    key->y = 0;
    index1 = 0;
    index2 = 0;
    for(counter = 0; counter < 256; counter++)
    {
        index2 = (key_data_ptr[index1] + state[counter] +
                index2) % 256;
        swap_byte(&state[counter], &state[index2]);

        index1 = (index1 + 1) % key_data_len;
    }
}

void rc4(unsigned char *buffer_ptr, int buffer_len,  rc4_key *key)
{
    unsigned char x;
    unsigned char y;
    unsigned char* state;
    unsigned char xorIndex;
    int counter;

    x = key->x;
    y = key->y;

    state = &key->state[0];
    for(counter = 0; counter < buffer_len; counter ++)
    {
        x = (x + 1) % 256;
        y = (state[x] + y) % 256;
        swap_byte(&state[x], &state[y]);

        xorIndex = (state[x] + state[y]) % 256;

        buffer_ptr[counter] ^= state[xorIndex];
    }
    key->x = x;
    key->y = y;
}

static void swap_byte(unsigned char *a, unsigned char *b)
{
    unsigned char swapByte;

    swapByte = *a;
    *a = *b;
    *b = swapByte;
}

@implementation NSString(Secret)

- (NSString *)MD5String{

    const char *original_str = [self UTF8String];
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5(original_str, (CC_LONG)strlen(original_str), result);
    NSMutableString *hash = [NSMutableString string];
    for (int i = 0; i < 16; i++)
        [hash appendFormat:@"%02X", result[i]];
    return [hash lowercaseString];
}
- (NSString *)hmacsha1WithKey:(NSString *)secret{
    unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH];
    memset(cHMAC, 0, CC_SHA1_DIGEST_LENGTH);

    CCHmac(kCCHmacAlgSHA1, secret.UTF8String, strlen(secret.UTF8String), self.UTF8String, strlen(self.UTF8String), cHMAC);
    NSData *HMACData = [NSData dataWithBytes:cHMAC length:sizeof(cHMAC)];
    const unsigned char *buffer = (const unsigned char *)[HMACData bytes];

    NSMutableString *hmacsha1 = [[NSMutableString alloc] init];
    for (int i = 0; i < HMACData.length; ++i){
        [hmacsha1 appendFormat:@"%02x", buffer[i]];
    }
    return hmacsha1;
}


-(NSString*)base64RC4
{
    char *Key = "Z&*6823jkI5MTY0ZWFl";
    return [self base64RC4WithKey:Key];
}
- (NSString*)base64RC4WithKey:(char*)Key{
    if(Key == NULL) return @"thisisawrongkey";
    rc4_key rc4key;
    
    prepare_key((unsigned char*)Key, (int)strlen(Key),	&rc4key);
    
    char* buffer=(char*)malloc([self length]);
    //    char buffer[256];
    memcpy(buffer, (char*)[self UTF8String], [self length]);
    rc4((unsigned char *)buffer, (int)[self length], &rc4key);
    
    
    NSData* base64data=[GTMBase64 encodeBytes:(const void *)buffer length:[self length]];
    NSString* base64result=[[NSString alloc] initWithData:base64data encoding:NSUTF8StringEncoding];

    if(buffer){
        free(buffer);
    }
    return base64result;
}
+(NSString*)decrypt:(NSData*)data key:(char*)Key
{
    rc4_key rc4key;

    prepare_key((unsigned char*)Key, (int)strlen(Key),	&rc4key);
    NSString* res=@"";
    if ([data length]>500000) {
        char* buffer=(char*)malloc([data length]);
        memcpy(buffer, (char*)[data bytes], [data length]);
        rc4((unsigned char *)buffer, (int)[data length], &rc4key);
        res=[NSString stringWithUTF8String:(const char*)buffer];
        free(buffer);
    }
    else{
        char buffer[500000] = {'\0'};
        memcpy(buffer, (char*)[data bytes], [data length]);
        rc4((unsigned char *)buffer, (int)[data length], &rc4key);
        res=[NSString stringWithUTF8String:(const char*)buffer];
    }
//    char buffer[500000] = {'\0'};
//    char buffer[100000]={0};
//    char* buffer=(char*)malloc(sizeof(char)*[data length]);
//    memset(buffer, 0, 100000);
//    DEBUGLOG(@"leng_data:%d,leng_res:%d,%@",[data length],[res length],res);
    return res;
}
+(Byte*)decryptByte:(Byte*)bytes key:(char*)Key len:(int)len
{
    rc4_key rc4key;

    prepare_key((unsigned char*)Key, (int)strlen(Key),	&rc4key);

//    char buffer[500000] = {'\0'};
//    memcpy(buffer, (char*)bytes, len);
    rc4((unsigned char *)bytes, len, &rc4key);
//    NSData* data=[NSData dataWithBytes:(const void *)bytes length:len];
    return bytes;
}

- (BOOL)regexWithRegular:(NSString *)regular{
    int status;
    int cflags = REG_EXTENDED;
    regmatch_t pmatch[1];
    const size_t nmatch = 1;
    regex_t reg;
    const char * pattern = regular.UTF8String;
    const char * buf = self.UTF8String;
    regcomp(&reg,pattern,cflags);//编译正则模式
    status = regexec(&reg,buf,nmatch,pmatch, 0);//执行正则表达式和缓存的比较
    regfree(&reg);
    
    if(status == 0){
        return YES;
    }else{
        return NO;
    }
    
    return YES;
}

@end
